package ar.com.sectorwine.entities;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.security.core.userdetails.UserDetails;

@Entity
@Table(name = "users", uniqueConstraints = { @UniqueConstraint(columnNames = { "username" }) })
public class Users implements Serializable, UserDetails, EliminableLogicamente {

	/**
	 * 
	 */
	private static final long serialVersionUID = 8886578197018917094L;

	@Id
	@Column(name = "username", nullable = false, unique = true)
	@NotEmpty(message = "{constraint.violation.notnull}")
	@NotNull(message = "{constraint.violation.notnull}")
	@Size(min = 1, max = 25, message = "{constraint.violation.size.1_25}")
	private String username;

	@NotEmpty(message = "{constraint.violation.notnull}")
	@NotNull(message = "{constraint.violation.notnull}")
	@Size(min = 8, max = 255, message = "{constraint.violation.size.8_255}")
	@Column(name = "password", nullable = false)
	private String password;

	@NotEmpty(message = "{constraint.violation.notnull}")
	@NotNull(message = "{constraint.violation.notnull}")
	@Size(min = 1, max = 25, message = "{constraint.violation.size.1_25}")
	@Column(name = "nombre", nullable = false)
	private String nombre;

	@NotEmpty(message = "{constraint.violation.notnull}")
	@NotNull(message = "{constraint.violation.notnull}")
	@Size(min = 1, max = 25, message = "{constraint.violation.size.1_25}")
	@Column(name = "apellido", nullable = false)
	private String apellido;

	@OneToMany(cascade = CascadeType.ALL)
	@JoinColumn(name = "username")
	private List<Authorities> authorities = new ArrayList<Authorities>();

	@Column(name = "accountNonExpired")
	private Boolean accountNonExpired = true;

	@Column(name = "accountNonLocked")
	private Boolean accountNonLocked = true;

	@Column(name = "credentialsNonExpired")
	private Boolean credentialsNonExpired = false;

	@NotEmpty(message = "{constraint.violation.notnull}")
	@NotNull(message = "{constraint.violation.notnull}")
	@Size(min = 1, max = 400, message = "{constraint.violation.size.1_25}")
	@Email(message = "{constraint.violation.email.format}")
	private String email;

	@AssertTrue(message = "{constraint.violation.assertTrue.tycAceptados}")
	@NotNull(message = "{constraint.violation.notnull}")
	private Boolean tycAceptados;

	private Boolean enabled;

	@OneToOne(cascade = CascadeType.ALL)
	private PerfilUsuario perfilUsuario;

	private String codigoConfimacion;
	
	@Temporal(value=TemporalType.DATE)
	private Date fechaCreacionPassword;
	
	@Column(name = "newsletter")
	private Boolean newsletter = false;

	public Boolean getNewsletter() {
		return newsletter;
	}

	public void setNewsletter(Boolean newsletter) {
		this.newsletter = newsletter;
	}

	@Override
	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Override
	public List<Authorities> getAuthorities() {
		return this.authorities;
	}

	@Override
	public boolean isEnabled() {
		return enabled;
	}

	@Override
	public boolean isAccountNonExpired() {
		return this.accountNonExpired;
	}

	@Override
	public boolean isAccountNonLocked() {
		return this.accountNonLocked;
	}

	public boolean isCredentialsNonExpired() {
		return this.credentialsNonExpired;
	}

	public boolean isCredentialsNonExpired(int caducidadDePassword) {
		
		if(this.getFechaCreacionPassword() != null){
			Calendar now = Calendar.getInstance();
			
			Calendar vencimiento = Calendar.getInstance();
			
			vencimiento.setTime(this.getFechaCreacionPassword());
			vencimiento.add(Calendar.MONTH, caducidadDePassword);
			
			return vencimiento.after(now);
		}else{
			return false;
		}
	}

	public void setAccountNonLocked(boolean accountNonLocked) {
		this.accountNonLocked = accountNonLocked;
	}

	public void setAccountNonExpired(boolean accountNonExpired) {
		this.accountNonExpired = accountNonExpired;
	}

	public void setAuthorities(List<Authorities> authorities) {
		this.authorities = authorities;
	}

	public void setCredentialsNonExpired(boolean credentialsNonExpired) {
		this.credentialsNonExpired = credentialsNonExpired;
	}

	public void setEnabled(Boolean enabled) {
		this.enabled = enabled;
	}

	public Boolean getTycAceptados() {
		return tycAceptados;
	}

	public void setTycAceptados(Boolean tycAceptados) {
		this.tycAceptados = tycAceptados;
	}

	public PerfilUsuario getPerfilUsuario() {
		return perfilUsuario;
	}

	public void setPerfilUsuario(PerfilUsuario perfilUsuario) {
		this.perfilUsuario = perfilUsuario;
	}

	public String getNombre() {
		return nombre;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public String getApellido() {
		return apellido;
	}

	public void setApellido(String apellido) {
		this.apellido = apellido;
	}

	@Override
	public void setBaja(Boolean baja) {
		setEnabled(baja);

	}

	@Override
	public Boolean getBaja() {
		return isEnabled();
	}

	public String getCodigoConfimacion() {
		return codigoConfimacion;
	}

	public void setCodigoConfimacion(String confimacionRegistro) {
		this.codigoConfimacion = confimacionRegistro;
	}

	@Override
	public boolean equals(Object o) {
		if (o instanceof Users && o != null && ((Users) o).username != null) {
			return ((Users) o).username.equals(this.username);
		}
		return false;

	}

	public Date getFechaCreacionPassword() {
		return fechaCreacionPassword;
	}

	public void setFechaCreacionPassword(Date fechaCreacionPassword) {
		this.fechaCreacionPassword = fechaCreacionPassword;
	}

}
